--- title: Signal To Noise Ratio for the OpenHSI Camera keywords: fastai sidebar: home_sidebar summary: "Includes an interactive SNR calculator." description: "Includes an interactive SNR calculator." nb_path: "04_snr.ipynb" ---
{% raw %}
/Users/eway/.pyenv/versions/3.8.3/lib/python3.8/site-packages/pandas/compat/__init__.py:97: UserWarning: Could not import the lzma module. Your installed Python is incomplete. Attempting to use lzma compression will result in a RuntimeError.
  warnings.warn(msg)
{% endraw %} {% raw %}
{% endraw %} {% raw %}
{% endraw %} {% raw %}
%time ref_model = Model6SV(tile_type=1.0,λ_array = λ_array) 
#takes about 20 s, 55 s with Teams running, 40 s with Zoom
ref_model.show()
{% endraw %} {% raw %}
class Widget_SNR(param.Parameterized):
    aperture_mm         = param.Number(4, bounds=(1,200),doc="aperture (mm)")
    focal_length_mm     = param.Number(16,doc="focal length (mm)")
    pixel_length_x_μm   = param.Number(25, bounds=(1,60),doc="pixel length x (μm)")
    pixel_length_y_μm   = param.Number(3.45, bounds=(1,60),doc="pixel length y (μm)")
    integration_time_ms = param.Number(10, bounds=(5,100), step=1,doc="integration time (ms)")
    bandwidth_nm        = param.Number(4, bounds=(0.1,20), step=0.1,doc="FWHM bandwidth (nm)")
    QE_model    = param.ObjectSelector(default="imx174qe", doc="Camera QE model", objects =
                        [f.split(".")[0] for f in os.listdir("assets") if ".csv" in f])
    surface_albedo      = param.Number(0.3, bounds=(0,1.0),doc="constant surface albedo reflectance")
    # diffraction efficiency unknown
    optical_trans_efficiency = param.Number(0.7, bounds=(0.1,1), step=0.05,doc="Optical transmission efficiency")
    #solar_zenith_deg = param.Number(0, bounds=(-60,60),doc="solar zenith angle (deg)")
    altitude_km      = param.Number(0.12, bounds=(0,None),doc="camera altitude (km)")
    
    wavelengths = λ_array#np.arange(0.4, .8, 0.004)
    ref_model = ref_model
    #ref_model = Model6SV(λ_array=wavelengths)
    
    @param.depends("altitude_km",watch=True)
    def _calc_rad(self):
        self.ref_model = Model6SV(alt=self.altitude_km)
        
    @param.depends("aperture_mm","focal_length_mm","pixel_length_x_μm","pixel_length_y_μm",
                   "integration_time_ms","bandwidth_nm","QE_model","optical_trans_efficiency","surface_albedo")#,"solar_zenith_deg")
    def view(self):
        
        self.f_num = self.focal_length_mm / self.aperture_mm
        self.A_d = self.pixel_length_x_μm*1e-6 * self.pixel_length_y_μm*1e-6
        
        # interpolation to OpenHSI wavelengths and remove NaNs
        self.QE = pd.read_csv(f"assets/{self.QE_model}.csv",names=["wavelength","QE_pct"], header=None)
        self.QE["wavelength"] /= 1000
        self.QE.insert(0,"type","manufacturer")
        self.QE = pd.concat( [ pd.DataFrame({"type":"6SV","wavelength":self.wavelengths}), self.QE] )
        self.QE.set_index("wavelength",inplace=True)
        self.QE.interpolate(method="cubicspline",axis="index",limit_direction="both",inplace=True)
        self.QE = self.QE[self.QE["type"].str.match("6SV")]
        self.QE.drop("type", 1,inplace=True)
        
        self.N = self.ref_model.photons * self.integration_time_ms*1e-3 * self.A_d * np.pi/(2*self.f_num)**2 * \
                    self.bandwidth_nm*1e-3 * self.QE["QE_pct"].to_numpy()/100 * self.optical_trans_efficiency * \
                    self.surface_albedo #* np.cos(np.deg2rad(self.solar_zenith_deg))
        
        self.table = hv.Table((self.wavelengths*1e3, np.sqrt(self.N)), 'wavelength (nm)', 'SNR')
        return hv.Curve(self.table).opts(tools=["hover"],width=600,height=200,ylim=(0,None))

widget = Widget_SNR(name="Interactive SNR Widget")
pn.Row(widget.param,widget.view)
{% endraw %} {% raw %}
df1 = pd.read_csv("assets/imx174qe.csv",names=["wavelength_nm","QE_pct"], header=None)
df2 = pd.read_csv("assets/imx273qe.csv",names=["wavelength_nm","QE_pct"], header=None)
df3 = pd.read_csv("assets/cmv2000qe.csv",names=["wavelength_nm","QE_pct"], header=None)
( hv.Curve(df1,label="imx174") * hv.Curve(df2,label="imx273") * hv.Curve(df3,label="cmv2000") ).opts(width=1000)
{% endraw %}